package org.geekbang.thinking.in.spring.bean.definition;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * 注解 BeanDefinition 实例
 *
 */
// 3、通过 @Import 方式来进行导入
@Import(AnnotationBeanDefinitionDemo.Config.class)
public class AnnotationBeanDefinitionDemo {

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class (配置类)
        applicationContext.register(Config.class);

        // 通过 BeanDefinition 注册 API 实现
        registerUserBeanDefinition(applicationContext, "wsq-user"); // 命名方式
        registerUserBeanDefinition(applicationContext); // 非命名方式

        // 启动应用上下文
        applicationContext.refresh();
        // 按类型依赖查找
        System.out.println("Config 类型的所有 Beans: " + applicationContext.getBeansOfType(Config.class));
        System.out.println("User 类型的所有 Beans: " + applicationContext.getBeansOfType(User.class));

        // 显示关闭上下文
        applicationContext.close();
    }

    /**
     * 命名 Bean 的注册方式
     * @param registry
     * @param beanName
     */
    public static void registerUserBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        beanDefinitionBuilder
                .addPropertyValue("id", 11)
                .addPropertyValue("name", "唐三");

        // 判断如果 beanName 参数存在时
        if (StringUtils.hasText(beanName)) {
            // 注册 BeanDefinition
            registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
        } else {
            // 非命名方式
            BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(), registry);
        }

    }

    public static void registerUserBeanDefinition(BeanDefinitionRegistry registry) {
        registerUserBeanDefinition(registry, null);
    }

    // 2、通过 @Component 方式
    @Component  // 定义当前类作为一个 Spring Bean
    public static class Config {

        // 1、通过 @Bean 的方式定义
        @Bean(name = {"user", "wang-user"})
        public User user() {
            User user = new User();
            user.setId(20L);
            user.setName("汪齐");
            return user;
        }

    }

}
